package jeconbond.experiment.market.equilibrium.generate;

import jeconbond.automata.INode;
import jeconbond.automata.IOutcome;
import jeconbond.automata.AutomataUtils;
import jeconbond.automata.behaviour.ListPlanWalker;
import jeconbond.automata.behaviour.IAutomataWalkListener;
import jeconbond.economic.agent.AutomataAgent;
import jeconbond.economic.market.strategy.IPerformPriceStrategy;
import jeconbond.economic.market.strategy.ObserveCostsProfitMerchantDecorator;
import jeconbond.economic.market.strategy.ProductNecessityMerchant;
import jeconbond.economic.resources.IResourceType;
import jeconbond.economic.resources.ResourceUtils;
import jeconbond.economic.systems.market.IMoneyAccount;
import jeconbond.economic.systems.market.MoneyAccount;
import jeconbond.experiment.generate.IAgentsCreator;
import jeconbond.experiment.market.equilibrium.MooreExperimentSettings;
import jeconbond.experiment.market.equilibrium.process.IMooreExperimentContext;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import laboratoryQ.experiment.process.IExperimentContext;

public class MooreAgentsCreator implements IAgentsCreator {
	@Override
	public AutomataAgent[] automata2agents(INode[] automatas, IExperimentContext iexperimentContext) {
		IMooreExperimentContext experimentContext = (IMooreExperimentContext) iexperimentContext;
		MooreExperimentSettings settings = experimentContext.getExperimentSettings();
		AutomataAgent[] agents = new AutomataAgent[settings.agentsCount];
		IAutomataWalkListener activityListener = experimentContext.getAutomataWalkListener();
		Map<IResourceType, double[]> concurrentPrices = 
			experimentContext.getConcurrentPricesMap();
		
		for (int i = 0; i < settings.agentsCount; i++) {
			INode root = automatas[i];
			AutomataAgent agent = new AutomataAgent(root);
			agent.setWalkingListener(activityListener);
			List<IOutcome> plan = new ArrayList<IOutcome>();
			AutomataUtils.easyTracePlan(root, plan);
			ListPlanWalker listPlWl = new ListPlanWalker(
					plan,
					agent.getInputRS(),
					agent.getOutputRS()
			);
			IMoneyAccount agentMoney = new MoneyAccount(settings.initMoney);
			double purchaseLevel = 1.0;
			ObserveCostsProfitMerchantDecorator observeCPMerch = new ObserveCostsProfitMerchantDecorator(
					agent,
					listPlWl,
					experimentContext.getRRS(),
					agentMoney,
					settings.observeCostsTraceLength,
					purchaseLevel
			);
			IPerformPriceStrategy performPriceStrategy = ResourceUtils.newConcurGreedPriceStrat(
					observeCPMerch, 
					settings.agentGreedPercent, 
					settings.concurrentPricePercent,
					concurrentPrices
			);
			((ProductNecessityMerchant)observeCPMerch.getSubmerchant())
				.setPerformPriceStrategy(performPriceStrategy);
			experimentContext.addServiceAgent(observeCPMerch);
			agent.setMerchant(observeCPMerch);
			agent.setWalkStrategy(listPlWl);
			agents[i] = agent;
		}
		return agents;
	}
}
